﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ufida.u9.ait.openapi.utils;
using UFIDA.U9.Base;
using UFIDA.U9.CBO.Enums;
using UFIDA.U9.CBO.MFG.BOM;
using UFIDA.U9.CBO.SCM.Bin;
using UFIDA.U9.CBO.SCM.Item;
using UFIDA.U9.CBO.SCM.Warehouse;
using UFIDA.U9.MO.Complete;
using UFIDA.U9.MO.Enums;
using UFIDA.U9.MO.MO;
using UFSoft.UBF.Business;

namespace ufida.u9.ait.openapi
{
    internal class CompRptBase
    {
        public static CompleteRpt ApproveDocEx(DocDTOData dto, CompleteRpt doc)
        {
            if (!String.IsNullOrEmpty(dto.DocDate))
            {
                //修改日期
                using (ISession session = Session.Open())
                {
                    doc.BusinessDate = DateTime.Parse(dto.DocDate);//单据日期
                    doc.CompleteDate = doc.BusinessDate;//完工日期
                    doc.ActualRcvTime = doc.BusinessDate;//实际入库日期
                    session.Commit();
                }
            }
            return ApproveDoc(doc);
        }
        public static CompleteRpt ApproveDoc(CompleteRpt doc)
        {
            doc = doc.Key.GetEntity();
            if (doc.DocState == CompleteRptStateEnum.Approved)
                throw new Exception($"单号[{doc.DocNo}]状态为已审");

            //审核
            //第一次调用状态可能是 开立->审核中 或 审核中->已审
            ApproveCompleteRpt bp = new ApproveCompleteRpt();
            bp.CurrentSysVersion = doc.SysVersion;
            bp.CompleteRpt = doc.Key;
            bp.Do();

            doc = doc.Key.GetEntity();
            if(doc.DocState== CompleteRptStateEnum.Approving)
            {
                //第一次调用后,状态=审核中,需要再次调用
                ApproveCompleteRpt bp1 = new ApproveCompleteRpt();
                bp1.CurrentSysVersion = doc.SysVersion;
                bp1.CompleteRpt = doc.Key;
                bp1.Do();
            }

            return doc;
        }

        public static CompleteRpt CreateDoc(CopyOfCompRptDTOData dto)
        {
            CompleteRpt doc;
            using (ISession session = Session.Open())
            {
                doc = CreateCompRpt(dto);
                session.Commit();
            }

            return doc;
        }

        private static CompleteRpt CreateCompRpt(CopyOfCompRptDTOData dto)
        {
            CompleteRpt doc = CompleteRpt.Create();
            //默认值处理
            HeadDefault(dto, doc);
            //完工数量,考虑双单位(库存单位/成本单位)
            HeadQty(dto, doc);
            //生产订单
            HeadSrc(dto, doc);
            //完工报告入库页签
            CreateLines(dto, doc);
            return doc;
        }

        private static void HeadSrc(CopyOfCompRptDTOData dto, CompleteRpt doc)
        {
            if (dto.MO == null)
                throw new Exception($"传入生产订单[MO]为空");
            MO mo = MO.Finder.Find($"DocNo='{dto.MO.Code}'");
            if (mo == null)
                throw new Exception($"查找生产订单失败!订单号:[{dto.MO.Code}]");
            //与预计产出中的物料做比对,支持联副产品的传入
            bool itemMatch = false;//料品是否匹配
            foreach (var output in mo.MOOutputs)
            {
                if (output.Item.Code == dto.ItemMaster.Code)
                    itemMatch = true;
            }
            if (!itemMatch)
            {
                throw new Exception($"生产订单[{dto.DocNo}],预计产出中的物料不包含传入物料[{dto.ItemMaster.Code}]");
            }
            //来源生产订单
            doc.RcvWh = mo.CompleteWh;
            doc.Bin = mo.CompleteBin;
            doc.CostField = mo.CostField;
            doc.MO = mo;
            if (mo.ItemMaster.ID == doc.Item.ID)
            {
                //主产品
                //项目=MO项目
                doc.Project = mo.Project;
            }
            else
            {
                //联副产品
                //项目 优先BOM上的项目,其次MO上的项目
                BOMMaster bom = BOMMaster.Finder.Find($"Status=2 and ItemMaster={doc.Item.ID} order by ID desc");
                if (bom != null && bom.Project != null)
                {
                    doc.Project = bom.Project;
                }
                else
                {
                    doc.Project = mo.Project;
                }
            }
        }

        private static void HeadDefault(CopyOfCompRptDTOData dto, CompleteRpt doc)
        {
            if (dto.DocNo == null || dto.DocNo.Length == 0)
                throw new Exception($"传入单号[DocNo]为空");
            //doc.DocNo = "自动编号";//单号
            //组织
            doc.Org = Context.LoginOrg;
            doc.PerformingOrg = Context.LoginOrg;
            doc.OwnerOrg = Context.LoginOrg;
            doc.RcvOrg = Context.LoginOrg;
            //单据类型
            if (dto.CompleteDocType == null)
                throw new Exception($"单据类型[CompleteDocType]为空");
            doc.CompleteDocType = EntityUtils.GetEntityByCode<CompleteRptDocType>(dto.CompleteDocType.Code);
            if (dto.BusinessDate == null)
            {
                doc.BusinessDate = DateTime.Now;
            }
            else
            {
                doc.BusinessDate = DateTime.Parse(dto.BusinessDate);
            }
            doc.CompleteDate = doc.BusinessDate;

            //料品
            if (dto.ItemMaster == null)
                throw new Exception($"传入料品[ItemMaster]为空");
            ItemMaster item = EntityUtils.GetEntityByCode<ItemMaster>(dto.ItemMaster.Code);
            if (item != null)
            {
                //料品
                doc.Item = item;
                doc.WhUOM = item.InventorySecondUOM;
                doc.StoreBaseUOM = item.InventorySecondUOM.BaseUOM;
                doc.ProductUOM = item.ManufactureUOM;
                doc.ProductBaseUOM = item.ManufactureUOM.BaseUOM;
                doc.CoUOM = item.CostUOM;
                doc.CostBaseUOM = item.CostUOM.BaseUOM;
            }
            //描述性弹性域
            if (dto.DescFlexField != null)
            {
                doc.DescFlexField = new UFIDA.U9.Base.FlexField.DescFlexField.DescFlexSegments();
                DTOUtils.DTOPropCopy(dto.DescFlexField, doc.DescFlexField);
            }

            //其它
            doc.SUToSBURate = 1;
            doc.PUToPBURate = 1;
            doc.PBUToSBURate = 1;
            doc.PBUToCBURate = 1;
            doc.CUToCBURate = 1;
            doc.OperationState = TargetOpStateEnum.GetFromValue(2);//工序状态=待转移
        }

        private static void HeadQty(CopyOfCompRptDTOData dto, CompleteRpt doc)
        {
            if (dto.CompleteQty <= 0) throw new Exception("CompleteQty 必填");
            doc.CompleteQty = dto.CompleteQty; //完工数量
            doc.CompleteQtyWhUOM = dto.CompleteQty;//完工数量-库存
            doc.CompleteQtyCoUOM = dto.CompleteQtyCoUOM > 0 ? dto.CompleteQtyCoUOM : dto.CompleteQty;//完工数量-成本
            doc.RcvQtyByWhUOM = doc.CompleteQtyWhUOM; //实际入库数量-库存
            doc.RcvQtyByProductUOM = doc.CompleteQtyWhUOM;//实际入库数量-生产
            doc.RcvQtyByCoUOM = doc.CompleteQtyCoUOM;//实际入库数量-成本
            doc.EligibleQty = doc.CompleteQtyWhUOM;//合格数量-库存
            doc.EligibleQtyCoUOM = doc.CompleteQtyCoUOM; //合格数量-成本
            if (dto.ScrapQty > 0)
            {
                doc.ScrapReason = ResTimeRptScrapReasonEnum.GetFromValue(dto.ScrapReason);//报废原因
                doc.ScrapQty = dto.ScrapQty;//报废数量-库存
                doc.ScrapQtyCoUOM = dto.ScrapQtyCoUOM > 0 ? dto.ScrapQtyCoUOM : dto.ScrapQty; //报废数量-成本

                doc.EligibleQty = doc.CompleteQty - doc.ScrapQty; //合格数量-库存
                doc.EligibleQtyCoUOM = doc.CompleteQtyCoUOM - doc.ScrapQtyCoUOM; //合格数量-成本
            }
            //转化率
            doc.PBUToCBURate = doc.CompleteQtyCoUOM / doc.CompleteQtyWhUOM;//库存-成本
        }

        /// <summary>
        /// 创建入库行数据
        /// </summary>
        /// <param name="dto"></param>
        /// <param name="doc"></param>
        private static void CreateLines(CopyOfCompRptDTOData dto, CompleteRpt doc)
        {
            if (dto.CompleteRptRcvLines != null && dto.CompleteRptRcvLines.Count > 0)
            {
                //dto传入 入库页签
                //创建多行入库实体
                int rowno = 0;
                foreach (var linedto in dto.CompleteRptRcvLines)
                {
                    CompleteRptRcvLine line = CompleteRptRcvLine.Create(doc);
                    rowno += 10;
                    //其他
                    line.PBUToSBURate = 1;
                    line.PBUToCBURate = 1;
                    line.LineNum = rowno;
                    line.CurrentOrg = doc.Org;
                    //数量
                    if (linedto.RcvQtyByWhUOM == 0) throw new Exception("RcvQtyByWhUOM为空");
                    line.RcvQtyByWhUOM = linedto.RcvQtyByWhUOM; //入库数量-库存
                    line.RcvQtyByProductUOM = line.RcvQtyByWhUOM; //入库数量-生产
                    line.RcvQtyCostUom = linedto.RcvQtyByCostUOM > 0 ? linedto.RcvQtyByCostUOM : linedto.RcvQtyByWhUOM;//入库数量-成本
                    //转化率
                    line.PBUToSBURate = line.RcvQtyByWhUOM / line.RcvQtyByProductUOM;//产品-库存
                    line.PBUToCBURate = line.RcvQtyCostUom / line.RcvQtyByProductUOM;//产品-成本
                    //仓库
                    if (string.IsNullOrEmpty(linedto.Wh?.Code))
                        throw new Exception("Wh为空");
                    line.Wh = EntityUtils.GetEntityByCode<Warehouse>(linedto.Wh.Code);
                    //库位
                    if (!string.IsNullOrEmpty(linedto.Bin?.Code))
                        line.Bin = EntityUtils.GetBin(line.Wh.Code, linedto.Bin.Code);
                    //批号
                    line.RcvLotNo = linedto.RcvLotNo;
                    if (!string.IsNullOrEmpty(dto.RcvLotEffectivedate))
                    {
                        line.RcvLotEffectivedate = DateTime.Parse(dto.RcvLotEffectivedate);//批号生效日期
                    }
                    if (!string.IsNullOrEmpty(dto.RcvLotDisableDate))
                    {
                        line.RcvLotDisableDate = DateTime.Parse(dto.RcvLotDisableDate);//批号失效日期
                    }

                    //存储类型
                    if (doc.ScrapQty > 0)
                    {
                        line.StorageType = UFIDA.U9.CBO.Enums.StorageTypeEnum.Wasted;
                    }
                    else
                    {
                        line.StorageType = UFIDA.U9.CBO.Enums.StorageTypeEnum.Useable;
                    }
                }
            }
            else if (doc.MO.CompleteWh != null || dto.Wh != null)
            {
                //未传入 入库页签
                //创建单行入库实体
                CompleteRptRcvLine line = CompleteRptRcvLine.Create(doc);
                //其他
                line.PBUToSBURate = 1;
                line.PBUToCBURate = 1;
                line.LineNum = 10;
                line.CurrentOrg = doc.Org;
                //数量
                line.RcvQtyByWhUOM = doc.RcvQtyByWhUOM; //入库数量-库存
                line.RcvQtyByProductUOM = doc.RcvQtyByProductUOM; //入库数量-生产
                line.RcvQtyCostUom = doc.RcvQtyByCoUOM; //入库数量-成本
                //转化率
                line.PBUToSBURate = line.RcvQtyByWhUOM / line.RcvQtyByProductUOM;//产品-库存
                line.PBUToCBURate = line.RcvQtyCostUom / line.RcvQtyByProductUOM;//产品-成本
                //存储地点
                if (dto.Wh != null && !string.IsNullOrEmpty(dto.Wh.Code))
                {
                    doc.RcvWh = EntityUtils.GetEntityByCode<Warehouse>(dto.Wh.Code);
                    line.Wh = doc.RcvWh;
                }
                else
                {
                    doc.RcvWh = doc.MO.CompleteWh;
                    line.Wh = doc.MO.CompleteWh;
                }
                //库位
                if (dto.Bin != null && !string.IsNullOrEmpty(dto.Bin.Code) && !string.IsNullOrEmpty(dto.Wh.Code))
                {
                    doc.Bin = EntityUtils.GetBin(dto.Wh.Code, dto.Bin.Code);
                    line.Bin = doc.Bin;
                }
                else
                {
                    doc.Bin = doc.MO.CompleteBin;
                    line.Bin = doc.MO.CompleteBin;
                }
                //批号
                line.RcvLotNo = dto.RcvLotNo;
                if (!string.IsNullOrEmpty(dto.RcvLotEffectivedate))
                {
                    line.RcvLotEffectivedate = DateTime.Parse(dto.RcvLotEffectivedate);//批号生效日期
                }
                if (!string.IsNullOrEmpty(dto.RcvLotDisableDate))
                {
                    line.RcvLotDisableDate = DateTime.Parse(dto.RcvLotDisableDate);//批号失效日期
                }
                //存储类型
                if (doc.ScrapQty > 0)
                {
                    line.StorageType = UFIDA.U9.CBO.Enums.StorageTypeEnum.Wasted;
                }
                else
                {
                    line.StorageType = UFIDA.U9.CBO.Enums.StorageTypeEnum.Useable;
                }
            }
        }
    }
}
